/*
 * intro: 基于[Flash]多文件上传控件
 * detail:  1. 多文件上传		
 * 			2. 取消队列中的文件	
 * 			3. 停止队列中的文件
 * 
 * usage: 
 * -----------------------------------------
 * var su = new Ext.ux.SWFUploadPanel({});
 * -----------------------------------------
 *  
 * author: nickevin@gmail.com
 * create: 01/02/09
 * 
*/

Ext.namespace('Ext.ux');

Ext.ux.SWFUploadPanel = function(config) {

	/* --------------------------- default config --------------------------- */

	this.width = 700, this.height = 300;
	this.file_upload_limit = 0;// this.prefixFileId = 'SWFUpload_0_';
	this.file_size_limit = 100 + 'MB';
	this.file_types = '*.jpg;*.doc;*.txt;*.pdf;*.xls';
	this.flash_url = '../../script/swfupload/swfupload.swf';
	this.upload_url = 'http://localhost:8080/SpringMVC/upload.do';

	if (!config.flash_url)
		config.flash_url = this.flash_url;
	if (!config.upload_url)
		config.upload_url = this.upload_url;
	if (!config.file_size_limit)
		config.file_size_limit = this.file_size_limit;
	if (!config.file_types)
		config.file_types = this.file_types;

	this.swfu = new SWFUpload({
				flash_url					: config.flash_url,
				upload_url					: config.upload_url, // Relative to the SWF file or absolute
				file_size_limit				: config.file_size_limit,
				file_types					: config.file_types,
				file_types_description		: "",
				file_upload_limit			: this.file_upload_limit,

				file_queued_handler			: this.fileQueued
						.createDelegate(this),
				file_queue_error_handler	: this.fileQueueError
						.createDelegate(this),
				// file_dialog_complete_handler : fileDialogComplete,// 选择文件完毕
				upload_start_handler		: this.uploadStart
						.createDelegate(this),
				upload_progress_handler		: this.uploadProgress
						.createDelegate(this),// 上传进度状态
				upload_error_handler		: this.uploadError
						.createDelegate(this),
				upload_success_handler		: this.uploadSuccess
						.createDelegate(this),
				upload_complete_handler		: this.uploadComplete
						.createDelegate(this)
			});

	this.store = new Ext.data.GroupingStore({
				proxy		: new Ext.data.HttpProxy({
							url		: '',
							method	: 'GET'
						}),
				reader		: new Ext.data.JsonReader({
							successProperty	: 'success',
							root			: 'data',
							totalProperty	: 'count',
							fields			: ['fileId', 'filename', 'size',
									'extention', 'status']
						}),
				sortInfo	: {
					field		: 'fileId',
					direction	: "ASC"
				},
				groupField	: 'extention'
			});

	this.cm = new Ext.grid.ColumnModel([new Ext.grid.CheckboxSelectionModel(),
			new Ext.grid.RowNumberer({
						header		: '序号',
						sortable	: true,
						width		: 40
					}), {
				header		: '文件编号',
				hidden		: true,
				dataIndex	: 'fileId'
			}, {
				id			: 'filename',
				header		: "文件名",
				dataIndex	: 'filename'
			}, {
				header		: "大小",
				sortable	: true,
				dataIndex	: 'size',
				width		: 40,
				summaryType	: 'sum',
				// renderer : this.renderSize
				renderer	: 'fileSize'
			}, {
				header		: "扩展名",
				width		: 40,
				dataIndex	: 'extention'
			}, {
				header		: "状态",
				dataIndex	: 'status',
				width		: 40,
				renderer	: this.renderStatus
			}]);

	this.btnBrowser = new Ext.Button({
				text	: '浏览',
				iconCls	: 'folder-explore',
				scope	: this,
				handler	: function() {
					this.swfu.selectFiles();// swfu.selectFile();
				}
			});

	this.btnUpload = new Ext.Button({
				text		: '上传',
				disabled	: true,
				iconCls		: 'control-play-blue',
				scope		: this,
				handler		: function() {
					this.pbar.setVisible(true);
					this.swfu.startUpload();

					this.btnStop.enable();
					this.btnRemove.disable();
				}
			});

	this.btnRemove = new Ext.Button({
				text		: '取消',
				iconCls		: 'control-stop-blue',
				disabled	: true,
				scope		: this,// required!
				handler		: function() {
					Ext.MessageBox.confirm('取消文件', '确定从队列中取消文件上传 ?',
							this.cancelUpload.createDelegate(this)
					);// required!
				}
			});

	this.btnStop = new Ext.Button({
				text		: '停止',
				iconCls		: 'control-eject-blue',
				disabled	: true,
				scope		: this,// required!
				handler		: function() {
					this.swfu.stopUpload();
				}
			});

	this.btnEmpty = new Ext.Button({
				text	: '清空队列',
				iconCls	: 'bin-empty',
				scope	: this,
				handler	: function() {
					var len = this.store.getCount();
					for (var i = 0; i < len; i++) {
						var rec = this.store.getAt(i);
						this.swfu.cancelUpload(this.store.getAt(i).data.fileId); // 不指定fileID则只取消首个文件上传
					}
					this.store.removeAll();

					this.btnUpload.disable();
					this.btnRemove.disable();
				}
			}
	);

	this.pbar = new Ext.ProgressBar({});
	this.pbar.setVisible(false);

	this.File = Ext.data.Record.create([{
				name	: 'filename'
			}, {
				name	: 'size'
			}, {
				name	: 'extention'
			}, {
				name	: 'status'
			}]);

	Ext.apply(this, config);

	/* --------------------------- override superclass property --------------------------- */

	Ext.ux.SWFUploadPanel.superclass.constructor.call(this, {
		title			: '上传文件列表',
		cm				: this.cm,
		store			: this.store,
		frame			: true,
		trackMouseOver	: true,
		stripeRows		: true,
		sm				: new Ext.grid.CheckboxSelectionModel(),
		tbar			: [this.btnBrowser, this.btnUpload, this.btnRemove,
				this.btnStop, '->', this.btnEmpty],
		bbar			: [this.pbar],
		plugins			: [new Ext.grid.GroupSummary()],
		viewConfig		: new Ext.grid.GroupingView({
			forceFit			: true,
			showGroupName		: true,
			enableNoGroups		: true,
			hideGroupedColumn	: true,
			groupTextTpl		: '{text} {[values.rs.length > 1 ? "(" + values.rs.length : ""]} {[values.rs.length > 1 ? "条记录)" : ""]}'
		}
		),
		loadMask		: {
			msg	: 'Loading ...'
		}
	}
	);

	this.sm = this.selModel;

	/* --------------------------- event handler --------------------------- */

	this.sm.on('selectionchange', this.onSelectionChange, this);
};

Ext.extend(Ext.ux.SWFUploadPanel, Ext.grid.GridPanel, {
			onSelectionChange	: function(sm) {
				var recs = sm.getSelections();
				var len = recs.length;
				if (len > 0) {
					this.btnRemove.enable();
				} else {
					this.btnRemove.disable();
				}
			},

			/* --------------------------- SWFUpload callback handler --------------------------- */

			fileQueued			: function(file) {
				var file = new this.File({
							fileId		: file.id,
							filename	: file.name,
							size		: file.size,
							extention	: file.type.substring(1).toLowerCase(),
							status		: SWFUpload.FILE_STATUS.QUEUED
						});
				this.store.add(file);

				this.btnUpload.enable();
				this.btnStop.enable();
			},
			fileQueueError		: function(file, errorCode, message) {
				switch (errorCode) {
					case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT :
						this.showErrorMsg('文件不允许超过 ' + this.file_size_limit
								+ '.');
						break;
					case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE :
						this.showErrorMsg('不允许上传空文件.');
						break;
					case SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED :
						this.showErrorMsg('上传文件数量不允许超过'
								+ this.file_upload_limit + '个.');
						break;
					case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE :
						this.showErrorMsg('不允许上传该类文件!');
						break;
					default :
						this.showErrorMsg('发生未知错误,错误代码:' + errorCode + '.');
						break;
				}
			},
			uploadStart			: function(file) {
				this.pbar.updateText('开始载入 ... ');
				return true;
			},
			uploadProgress		: function(file, bytesLoaded) {
				var rec = this.getCurrentRec(file.id);

				if (bytesLoaded / file.size != 1) {
					this.setCurrentSatus(rec, file.filestatus);
					/*	this.pbar.updateProgress(bytesLoaded / file.size, file.name + '  上传进度:  (' + this.renderSize(bytesLoaded) + ' of ' + this.renderSize(file.size) + ')');*/
					this.pbar.updateProgress(bytesLoaded / file.size,
							'  上传进度:  (' + bytesLoaded + ' of ' + file.size
									+ ')'
					);
				} else {
					this.setCurrentSatus(rec, file.filestatus);
					this.pbar.reset();
				}
			},
			uploadSuccess		: function(file, serverData) {
				var rec = this.getCurrentRec(file.id);

				var msg = Ext.decode(serverData);
				var result = msg.success;
				if (result) {
					this.setCurrentSatus(rec, file.filestatus);
					this.btnUpload.disable();
				}
			},
			uploadComplete		: function(file) {
				// alert(file.filestatus + '\n' + this.swfu.getStats().files_queued);
				if (file.filestatus == -4
						&& this.swfu.getStats().files_queued > 0) {
					this.swfu.startUpload(); // required! 自动上传下一个 否则只上传首个
				} else {
					this.pbar.reset(true);// 重置并隐藏
				}
			},
			uploadError			: function(file, errorCode, message) {
				var rec = this.getCurrentRec(file.id);

				switch (errorCode) {
					case SWFUpload.UPLOAD_ERROR.HTTP_ERROR :
						this.handlerUploadError('上传文件出错. 消息代码: ' + errorCode
										+ ' .', rec);
						break;
					case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED :
						// showErrorMsg('队列中文件被取消. 消息代码: ' + errorCode + ' .');
						break;
					case SWFUpload.UPLOAD_ERROR.UPLOAD_FAILED :
						this.handlerUploadError('上传文件失败. 消息代码: ' + errorCode
										+ ' .', rec);
						break;
					case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED :
						Ext.Msg.show({
									title	: '确认信息',
									icon	: Ext.MessageBox.INFO,
									msg		: '正在上传中的文件被停止,此文件即将返回队列等待上传.',
									buttons	: Ext.Msg.OK,
									fn		: this.stopUpload.createDelegate(
											this, [rec]
									)
								});
						break;
					case SWFUpload.UPLOAD_ERROR.IO_ERROR :
						this.handlerUploadError('选择上传的文件已被删除, 请重新选择. 消息代码: '
										+ errorCode + ' .', rec);
						break;
					default :
						this.handlerUploadError('发生未知错误,消息代码:' + errorCode
										+ '.', rec);
						break;
				}
			},
			handlerUploadError	: function(msg, rec) {
				this.showErrorMsg(msg);
				this.setCurrentSatus(rec, -3);
				this.btnUpload.disable();
			},
			cancelUpload		: function(btn) {
				if (btn == 'yes') {
					var recs = this.sm.getSelections();
					var len = recs.length;
					for (var i = 0; i < len; i++) {
						this.swfu.cancelUpload(recs[i].data.fileId);
						this.store.remove(recs[i]);
					}
				}
			},
			stopUpload			: function(rec) {
				this.setCurrentSatus(rec, -1);

				this.btnUpload.enable();
				this.btnStop.disable();

				this.pbar.reset(true);
			},

			/* --------------------------- extra function --------------------------- */

			/*renderSize : function(size) {
				var KB = 1024;
				var MB = 1024 * KB;

				if (size < MB) {
					if (size < KB) {
						return size + ' B'.italics();
					} else {
						return Math.ceil(size / KB) + ' KB'.italics();
					}
				} else {
					return Math.ceil(100 * size / MB) / 100 + ' MB'.italics();
				}
			},*/
			renderStatus		: function(status) {
				switch (status) {
					case -1 :
						return ('队列中'.fontcolor('silver'));
					case -2 :
						return ('上传中...'.fontcolor('purple'));
					case -3 :
						return ('错误'.fontcolor('red'));
					case -4 :
						return ('完成'.fontcolor('green'));
					case -5 :
						return ("取消");
				}
			},
			setCurrentSatus		: function(rec, status) {
				rec.set('status', status);
				rec.commit();// 去除'修改'标记
			},
			showErrorMsg		: function(msg) {
				Ext.Msg.show({
							title	: '错误',
							msg		: msg,
							buttons	: Ext.Msg.OK,
							icon	: Ext.MessageBox.ERROR
						});
			},
			getCurrentRec		: function(fileId) {
				var idx = this.store.find('fileId', fileId);
				return this.store.getAt(idx);
			}
		});